#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "SerialSocket.hpp"
#include "List.hpp"
#include <string.h>

SemaphoreHandle_t rx_sem;
char uart_rx_buffer[1024];
uint16_t uart_rx_size = 0;

class Portable : public SerialSocketPortable {
public:
    /* 串口移植相关. */
    virtual bool open(){
        return true;
    }

    virtual bool close(){
        return true;
    }

    virtual unsigned int read(void *buffer,unsigned int size){
        uart_rx_size = 0;
        HAL_UARTEx_ReceiveToIdle_DMA(&huart2,(uint8_t*)buffer,size);
        xSemaphoreTake(rx_sem,portMAX_DELAY);
        return uart_rx_size;
    }

    virtual unsigned int write(void *buffer,unsigned int size){
        HAL_UART_Transmit(&huart2,(uint8_t*)buffer,size,HAL_MAX_DELAY);
        return size;
    }
    /* 操作系统移植相关. */
    virtual int getSemaphore(){
        SemaphoreHandle_t sem = xSemaphoreCreateBinary();
        this->sems.append(sem);
        return this->sems.getSize() - 1;
    }

    virtual bool freeSemaphore(int sem_number){
        return true;
    }

    virtual bool takeSemaphore(int sem_number,int timeout){
        if ( timeout < 0 ){
            xSemaphoreTake(this->sems.get(sem_number),portMAX_DELAY);
        }else{
            xSemaphoreTake(this->sems.get(sem_number),(unsigned int)timeout);
        }
        return true;
    }

    virtual bool releaseSemaphore(int sem_number){
        xSemaphoreGive(this->sems.get(sem_number));
        return true;
    }
private:
    List<SemaphoreHandle_t> sems;
};

TaskHandle_t task;
TaskHandle_t task2;

char message = 0;
char message2 = 0;

void task_entry(void *args){
    SerialSocket *s = (SerialSocket*)args;
    volatile unsigned int tx_size = 0;
    s->write(&message,1);
    while ( true ){
        s->read(&message,1);
        message += 1;
        vTaskDelay(1000);
        tx_size = 0;
        tx_size = s->write(&message,1);
        tx_size = tx_size;
    }
}

void task2_entry(void *args){
    SerialSocket *s = (SerialSocket*)args;
    volatile unsigned int tx_size = 0;
    s->write(&message2,1);
    while ( true ){
        s->read(&message2,1);
        message2 += 1;
        vTaskDelay(1000);
        tx_size = 0;
        tx_size = s->write(&message2,1);
        tx_size = tx_size;
    }
}

extern "C"
void app_entry(const void *args){
    
    /* 初始化信号量. */
    rx_sem = xSemaphoreCreateBinary();
    Portable portable;
    SerialSockets *ss = SerialSockets::getInstance(&portable,1024);
    SerialSocket *s = ss->get(100);
    SerialSocket *s1 = ss->get(80);
    
    xTaskCreate(task_entry,"Task",1024,s,5,&task);
    xTaskCreate(task2_entry,"Task2",1024,s1,5,&task2);
    while ( true ){
        ss->eventHandler();
    }
}

void *operator new(size_t size){
    return pvPortMalloc(size);
}

void *operator new[](size_t size){
    return pvPortMalloc(size);
}

void operator delete(void *mem){
    vPortFree(mem);
    return;
}

void operator delete[](void *mem){
    vPortFree(mem);
    return;
}

extern "C"
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart,uint16_t size){
    if ( huart->Instance == USART2 ){
        /* EIA422 CH1. */
        BaseType_t temp;
        xSemaphoreGiveFromISR(rx_sem,&temp);
        uart_rx_size = size;
    }
}

